/*
 * author: Andriamananony, Meß, Falk
 */

package start;

import plan.Plan;
import schedule.IterateProductOrder;
import schedule.IterateVariants;
import util.JSONParser;
import util.TimeLog;
import auftrag.Auftrag;
import auftrag.Ressource;
import constraints.AllOrdersPlanned;
import constraints.DueDate;
import constraints.IConstraint;
import constraints.NoMachineOverload;
import constraints.OperationOrder;

public class Start {

	public static void main(String[] args) {
		int sum = 0;
		int it = 2;
		JSONParser parser = new JSONParser("beispieldata_1.json");
		parser.print();
		/**
		 * Wir nutzen zwei Verfahren: -iteriere über verschiedenen Varianten für
		 * die Produkte -iteriere über die Reihenfolge der Produkte bei der
		 * Einplanung
		 * 
		 * Annahme: Zwei Aufträge sind dann in einer Nachbarschaft, wenn die
		 * Reihenfolge, mit der ihre Produkte einsortiert werden, ähnlich sind,
		 * oder sie sich nur in Varianten unterscheiden
		 * 
		 * Beobachtungen: Das iterative Verfahren über Varianten zeigt schnellen
		 * Erfolg, wohl weil dadurch die Last langsam gleichmäßig auf alle
		 * Maschinen verteilt wird. Das ändern der Reihenfolge von Produkten
		 * nach dem Zufallsprinzip bringt allerdings gemessen an der Laufzeit
		 * nur geringen Erfolg, wohl weil es zu viele gleichartige Produkte
		 * gibt.
		 * 
		 * Möglich ist, dass eine Kombination der beiden noch schneller zu
		 * besseren Ergebnissen führt! (Memo an mich selbst: Für Contest
		 * testen!)
		 */
		for (int i = 0; i < it; i++) {

			TimeLog.logInfo("=============================================");
			TimeLog.logInfo("=== Plan " + i);
			TimeLog.logInfo("=============================================");

			Plan p = new Plan();

			for (Ressource r : parser.getRessources())
				r.clear();

			if (i == 1) {
				// Im ersten Schritt wird ein Verfahren getestet, das die
				// Variante für ein zufälliges Produkt ändert
				IterateVariants itv = new IterateVariants();
				p = itv.makePlan(parser.getOrders(), parser.getRessources());
			} else {
				// Im zweiten Schritt wird ein Verfahren getestet, das in jedem
				// Schritt die Reihenfolge von ein oder zwei Produkten ändert
				IterateProductOrder ipo = new IterateProductOrder();
				p = ipo.makePlan(parser.getOrders(), parser.getRessources());
			}

			TimeLog.logInfo("Plan created!");

			p.print();

			// Prüfen der Constraints
			IConstraint c1 = new AllOrdersPlanned();
			IConstraint c2 = new NoMachineOverload();
			IConstraint c3 = new OperationOrder();
			IConstraint c4 = new DueDate();

			if (c1.isMetBy(p, parser.getOrders())) {
				System.out.println("Alle Aufträge eingeplant!");
			}
			if (c2.isMetBy(p, parser.getOrders())) {
				System.out.println("Keine Doppelbelegung!");
			}
			if (c3.isMetBy(p, parser.getOrders())) {
				System.out.println("Produktionsreihenfolge eingehalten!");
			}
			if (c4.isMetBy(p, parser.getOrders())) {
				System.out.println("Alle Aufträge pünktlich abgearbeitet!");
			}

			for (Auftrag a : parser.getOrders()) {
				System.out.println("Auftragsnummer: " + a.getAuftragsnummer()
						+ "\t || Auftragsende: " + a.getEndDate()
						+ "\t || Auftragsdeadline: " + a.getDeadline()
						+ "\t || Auftragspriorität: " + a.getPriority());
			}
			System.out.println(p.getQuality());
		}

	}
}
